<script setup lang="ts">
import ContentFilterDialog from '@/components/Dialogs/ContentFilterDialog.vue'
import { useContentStore, useDialogStore } from '@/stores'
import { Torrent, TreeNode } from '@/types/vuetorrent'
import { storeToRefs } from 'pinia'
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useDisplay } from 'vuetify'
import { VVirtualScroll } from 'vuetify/components/VVirtualScroll'
import ContentNode from './ContentNode.vue'

const props = defineProps<{ torrent: Torrent; isActive: boolean }>()

const { height: deviceHeight } = useDisplay()
const contentStore = useContentStore()
const { rightClickProperties, filenameFilter, flatTree, internalSelection, lastSelected, timerForcedPause, isTimerActive } = storeToRefs(contentStore)
const dialogStore = useDialogStore()

const scrollView = ref<VVirtualScroll>()

const height = computed(() => {
  // 48px for the tabs and page title
  // 64px for the toolbar
  // 12px for the padding (top and bottom)
  // 56px for the filter text field
  // 8px for its top margin
  return deviceHeight.value - 48 * 2 - 64 - 12 * 2 - 56 - 8
})

async function onRightClick(e: MouseEvent | Touch, node: TreeNode) {
  if (rightClickProperties.value.isVisible) {
    rightClickProperties.value.isVisible = false
    await nextTick()
  }

  Object.assign(rightClickProperties.value, {
    isVisible: true,
    offset: [e.pageX, e.pageY],
    hash: props.torrent.hash
  })

  if (internalSelection.value.size <= 1) {
    internalSelection.value = new Set([node.fullName])
    lastSelected.value = node.fullName
  }
}

// mobile long press
const timer = ref<NodeJS.Timeout>()

function startPress(e: Touch, node: TreeNode) {
  timer.value = setTimeout(() => {
    onRightClick(e, node)
  }, 500)
}

function endPress() {
  clearTimeout(timer.value)
}

// END mobile long press

watch(
  () => props.isActive,
  isActive => {
    if (isActive && !timerForcedPause.value) contentStore.resumeTimer()
    else contentStore.pauseTimer()
  }
)

onMounted(() => {
  props.isActive && contentStore.resumeTimer()
  document.addEventListener('keydown', handleKeyboardInput)
})
onBeforeUnmount(() => {
  contentStore.$reset()
  document.removeEventListener('keydown', handleKeyboardInput)
})

function pause() {
  timerForcedPause.value = true
  contentStore.pauseTimer()
}

function resume() {
  timerForcedPause.value = false
  contentStore.resumeTimer()
}

function openFilterDialog() {
  dialogStore.createDialog(ContentFilterDialog)
}

function handleKeyboardInput(e: KeyboardEvent) {
  enum KeyNames {
    ArrowUp = 'ArrowUp',
    ArrowDown = 'ArrowDown',
    ArrowLeft = 'ArrowLeft',
    ArrowRight = 'ArrowRight',
    Spacebar = ' '
  }

  const pressedKey = e.key as KeyNames
  if (dialogStore.hasActiveDialog || !Object.values(KeyNames).includes(pressedKey)) {
    return false
  }

  e.preventDefault()
  const oldCursor = flatTree.value.findIndex(node => node.fullName === lastSelected.value)
  let newCursor = oldCursor

  switch (pressedKey) {
    case KeyNames.ArrowUp:
      if (oldCursor > 0) {
        newCursor--
      }
      break
    case KeyNames.ArrowDown:
      if (oldCursor < flatTree.value.length - 1) {
        newCursor++
      }
      break
    case KeyNames.ArrowLeft:
    case KeyNames.ArrowRight:
      contentStore.openNode(e, flatTree.value[oldCursor])
      break
    case KeyNames.Spacebar:
      contentStore.toggleFileSelection(flatTree.value[oldCursor]).then()
      break
  }

  if (oldCursor !== newCursor) {
    lastSelected.value = flatTree.value[newCursor].fullName
    internalSelection.value = new Set([lastSelected.value])
    scrollView.value?.scrollToIndex(newCursor - Math.floor(height.value / 68 / 2))
  }

  return true
}
</script>

<template>
  <v-card>
    <div class="mt-2 mx-3 d-flex flex-gap align-center">
      <v-text-field v-model="filenameFilter" hide-details clearable :placeholder="$t('torrentDetail.content.filter_placeholder')" @keydown.stop />

      <v-tooltip :text="$t('torrentDetail.content.filter.activator')" location="bottom">
        <template #activator="{ props }">
          <v-btn v-bind="props" icon="mdi-select-multiple" color="primary" @click="openFilterDialog" />
        </template>
      </v-tooltip>

      <v-tooltip :text="isTimerActive ? $t('common.pause') : $t('common.resume')" location="bottom">
        <template #activator="{ props }">
          <v-btn v-bind="props" :icon="isTimerActive ? 'mdi-timer-pause' : 'mdi-timer-play'" color="primary" @click="isTimerActive ? pause() : resume()" />
        </template>
      </v-tooltip>
    </div>

    <v-virtual-scroll ref="scrollView" :items="flatTree" :height="height" item-height="68" class="pa-2">
      <template #default="{ item }">
        <ContentNode
          :node="item"
          @touchcancel="endPress"
          @touchend="endPress"
          @touchmove="endPress"
          @touchstart="startPress($event.touches.item(0)!, item)"
          @onRightClick="(e, node) => onRightClick(e, node)" />
      </template>
    </v-virtual-scroll>
  </v-card>
</template>
